home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / sudo-1.000 / sudo-1 / sudo-1.2 / check.c next >
C/C++ Source or Header  |  1995-03-08  |  7KB  |  292 lines

  1. /*
  2.  *  sudo version 1.1 allows users to execute commands as root
  3.  *  Copyright (C) 1991  The Root Group, Inc.
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 1, or (at your option)
  8.  *  any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  If you make modifications to the source, we would be happy to have
  20.  *  them to include in future releases.  Feel free to send them to:
  21.  *      Jeff Nieusma                       nieusma@rootgroup.com
  22.  *      3959 Arbol CT                      (303) 447-8093
  23.  *      Boulder, CO 80301-1752             
  24.  *
  25.  *******************************************************************
  26.  *
  27.  *  check.c
  28.  *
  29.  *  check_user() only returns if the user's timestamp file
  30.  *  is current or if they enter a correct password.
  31.  *
  32.  *  Jeff Nieusma  Thu Mar 21 22:39:07 MST 1991
  33.  */
  34.  
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <strings.h>
  38. #include <fcntl.h>
  39. #include <sys/param.h>
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #include <sys/time.h>
  43. #include <sys/file.h>
  44. #include <pwd.h>
  45. #include "sudo.h"
  46.  
  47. #ifdef LINUX
  48. #include <sys/types.h>
  49. #endif
  50.  
  51. #ifdef SHADOW_PWD
  52. #include <shadow.h>
  53. #define crypt pw_encrypt
  54. #endif
  55.  
  56. char *getpass();
  57.  
  58. static int  check_timestamp();
  59. static void check_passwd();
  60. static void update_timestamp();
  61. static void reminder();
  62. static char *timestampfile_p;
  63.  
  64. static int  timedir_is_good;
  65.  
  66.  
  67. /********************************************************************
  68.  *
  69.  *  check_user()
  70.  *
  71.  *  This function only returns if the user can successfully
  72.  *  verify who s/he is.  
  73.  */
  74.  
  75. void check_user()
  76. {
  77. register int rtn;
  78.  
  79. umask ( 077 );              /* make sure the timestamp files are private */
  80.  
  81. if ( setuid (0) ) {         /* have to be root to see timestamps */
  82.     perror("setuid(0)");
  83.     exit(1);
  84.     }
  85. rtn = check_timestamp();    
  86. #ifdef LINUX
  87. if ( setreuid (uid, -1) ) {      /* don't want to be root longer than necessary */
  88. #else 
  89. if ( setruid (uid) ) {      /* don't want to be root longer than necessary */
  90. #endif
  91.     perror("setruid(uid)");
  92.     exit(1);
  93.     }
  94.  
  95. if ( rtn && uid )           /* if timestamp is not current... */
  96.     check_passwd(); 
  97.  
  98. if ( setuid (0) ) {         /* have to be root to play with timestamps */
  99.     perror("setuid(0)");
  100.     exit(1);
  101.     }
  102. update_timestamp();
  103. #ifdef LINUX
  104. if ( setreuid (uid, -1) ) {      /* don't want to be root longer than necessary */
  105. #else
  106. if ( setruid (uid) ) {      /* don't want to be root longer than necessary */
  107. #endif
  108.     perror("setruid(uid)");
  109.     exit(1);
  110.     }
  111.  
  112. umask ( 022 );              /* want a real umask to exec() the command */
  113.  
  114. }
  115.  
  116.  
  117.  
  118.  
  119. /********************************************************************
  120.  *
  121.  *  check_timestamp()
  122.  *
  123.  *  this function checks the timestamp file.  If it is within
  124.  *  TIMEOUT minutes, no password will be required
  125.  */
  126.  
  127. static int check_timestamp()
  128. {
  129. static char timestampfile[MAXPATHLEN+1];
  130. register char *p;
  131. struct stat statbuf;
  132. register int timestamp_is_old = -1;
  133. time_t now;
  134.  
  135.  
  136. sprintf ( timestampfile, "%s/%s", TIMEDIR, user );
  137. timestampfile_p = timestampfile;
  138.  
  139. timedir_is_good = 1;  /* now there's an assumption for ya... */
  140.  
  141.  
  142. /* walk through the path one directory at a time */
  143.  
  144. for ( p=timestampfile+1; p=index(p,'/'); *p++='/' ) {
  145.     *p='\0';
  146.     if ( stat(timestampfile,&statbuf) < 0) {
  147.         if ( strcmp ( timestampfile, TIMEDIR ))
  148.         fprintf ( stderr, "Cannot stat() %s\n", timestampfile );
  149.     timedir_is_good = 0;
  150.         *p='/';
  151.     break;
  152.     }
  153.     }
  154.  
  155.  
  156. if ( timedir_is_good ) {            /* if all the directories are stat()able */ 
  157.     if ( stat(timestampfile, &statbuf) ) { /* does the file exist?    */
  158.         if ( uid ) reminder();             /* if not, do the reminder */
  159.     timestamp_is_old=1;                /* and return (1)          */
  160.         }
  161.     else {                                 /* otherwise, check the time */
  162.     now = time ( (time_t *) NULL );
  163.     if ( now - statbuf.st_mtime < 60 * TIMEOUT )
  164.         timestamp_is_old = 0;          /* if file is recent, return(0) */
  165.     else
  166.         timestamp_is_old = 1;          /* else make 'em enter password */
  167.     }
  168.     }
  169.  
  170. /* there was a problem stat()ing a directory */
  171.  
  172. else {
  173.     timestamp_is_old = 1;                   /* user has to enter password */
  174.     if ( mkdir (TIMEDIR, 0700 ) ) {         /* make the TIMEDIR directory */
  175.     perror("check_timestamp: mkdir");
  176.     timedir_is_good = 0;
  177.     }
  178.     else {
  179.     timedir_is_good = 1;                /* TIMEDIR now exists         */
  180.     reminder();
  181.     }
  182.     }
  183.  
  184. return (timestamp_is_old);
  185.  
  186. }
  187.  
  188.  
  189.  
  190.  
  191.  
  192. /********************************************************************
  193.  *
  194.  *  update_timestamp()
  195.  *
  196.  *  This function changes the timestamp to now
  197.  */
  198.  
  199. static void update_timestamp()
  200. {
  201. register int fd;
  202.  
  203. if ( timedir_is_good ) {
  204.     unlink ( timestampfile_p );
  205.     if (( fd = open (timestampfile_p, O_WRONLY|O_CREAT|O_TRUNC, 0600 )) < 0 )
  206.     perror( "update_timestamp: open" );
  207.     close (fd);
  208.     }
  209. }
  210.  
  211.  
  212.  
  213.  
  214.  
  215. /********************************************************************
  216.  *
  217.  *  check_passwd()
  218.  *
  219.  *  This function grabs the user's password and checks with 
  220.  *  the password in /etc/passwd
  221.  */
  222.  
  223. static void check_passwd()
  224. {
  225. char *crypt();
  226. struct passwd *pw_ent;
  227. char *encrypted;                          /*  this comes from /etc/passwd  */
  228. char *pass;                               /*  this is what gets entered    */
  229. register int counter=TRIES_FOR_PASSWORD;
  230. #ifdef SHADOW_PWD
  231. struct spwd *sp;
  232. #endif
  233.  
  234. if ( (pw_ent = getpwuid( uid )) == NULL ) {
  235.     sprintf ( user, "%u", uid );
  236.     log_error( GLOBAL_NO_PW_ENT );
  237.     inform_user ( GLOBAL_NO_PW_ENT );
  238.     exit (1);
  239.     }
  240. #ifdef SHADOW_PWD
  241. sp = getspnam(pw_ent->pw_name);
  242. if (sp)
  243.     pw_ent->pw_passwd = sp->sp_pwdp;
  244. #endif
  245. encrypted = pw_ent -> pw_passwd;
  246.  
  247. /* you get TRIES_FOR_PASSWORD times to guess your password */
  248.  
  249. while ( counter > 0 ) {
  250.     pass = getpass ( "Password:" );
  251.     if ( *pass == (char)NULL ) exit(0);
  252.     if ( !strcmp(encrypted, crypt(pass,encrypted)))
  253.  
  254.         return;                      /*  if the passwd is correct return() */
  255.     -- counter;                                  /*  otherwise, try again  */
  256.     fprintf ( stderr, "%s\n", INCORRECT_PASSWORD );
  257.     }
  258.  
  259. log_error( PASSWORD_NOT_CORRECT );
  260. inform_user ( PASSWORD_NOT_CORRECT );
  261.  
  262. exit (1);
  263.  
  264. }
  265.  
  266.  
  267.  
  268.  
  269. /********************************************************************
  270.  *
  271.  *  reminder()
  272.  *
  273.  *  this function just prints the the reminder message
  274.  */
  275.  
  276. static void reminder()
  277. {
  278.  
  279. fprintf(stderr,"\n%s\n%s\n%s\n\n%s\n%s\n\n%s\n%s\n\n", 
  280.  
  281. "    sudo version 1.1, Copyright (C) 1991 The Root Group, Inc.",
  282. "    sudo comes with ABSOLUTELY NO WARRANTY.  This is free software,",
  283. "    and you are welcome to redistribute it under certain conditions.",
  284.  
  285. "We trust you have received the usual lecture from the local Systems",
  286. "Administrator. It usually boils down to these two things:",
  287.  
  288. "        #1) Respect the privacy of others.",
  289. "        #2) Think before you type."
  290. );
  291. }
  292.